Моноидом называется тройка (M, #, u), где # - ассоциативная бинарная операция на M, а u - ее единичный элемент.
Моноид полугруппа с нейтральным элементом. m # u = m = u # m
(P -> M, \f1 f2 -> \p -> f1 p # f2 p, \p -> e)
Если (M, #, e) и (P, @, u) – моноиды, то функция f :: M -> P называется гомоморфизмом между этими двумя моноидами, если f (m1 # m2) = f m1 @ f m2 для всех m1, m2 из M. чему равно u ?
Списочным гомоморфизмом называется гомоморфизм из моноида (списки, append, пустой список) в какой-либо другой моноид.
То есть, функция f называется списочным гомоморфизмом, если существует оператор #, такой, что f (xs ++ ys) = f xs # f ys. Это свойство позволяет независимо вычислить результаты применения функции для подсписков, и собрать из них результат для всего списка при помощи #.
# | u | f | |
---|---|---|---|
sum | + | 0 | \x -> x |
length | + | 0 | \x -> 1 |
filter p | ++ | [] | \x -> if (p x) then [x] else [] |
map f | ++ | [] | \x -> f x |
sort | merge | [] | \x -> [x] |
Чрезвычайно важно, что благодаря ассоциативности @, в выражении x1 @ x2 @ x3 @ ... @ xn можно расставлять скобки как угодно, вычисляя его в любом порядке (надо, однако, помнить, что @ не обязан быть коммутативным).
f ~ (map, reduce)
f [x] = map x
reduce A::[] B::[] = A @ B
© Евгений Кирпичёв
regEx = /^(a+ b* c)*$/
s0 --a--> s1
s1 --a--> s1
s1 --b--> s2
s1 --с--> s0 // bingo
s2 --b--> s2
s2 --c--> s0 // bingo
s? --?--> s3
regEx = /(a+ b* c)*/
a | b | c | |
---|---|---|---|
s0 | s1 | s3 | s3 |
s1 | s1 | s2 | s0 |
s2 | s3 | s2 | s0 |
s3 | s3 | s3 | s3 |
эндоморфизм на S
map x = \s -> fx s -- fx – функция-столбец
reduce f g = f . g
a | b | c | |
---|---|---|---|
s0 | s1 | s3 | s3 |
s1 | s1 | s2 | s0 |
s2 | s3 | s2 | s0 |
s3 | s3 | s3 | s3 |
Если функция f выражается и в виде левой, и в виде правой свертки с одинаковым начальным значением (но, возможно, разной операцией #), то она является списочным гомоморфизмом - и, следовательно, допускает параллельное и инкрементальное вычисление с помощью дерева.
Операция сравнения есть везде, но равны ли наши деревья?
let a = list2tree [1,5,3,2]
a == a?
полиморфизм
class Eq a where
(==) :: a -> a -> Bool
(==) :: (Eq a) => a -> a -> Bool
instance Eq Integer where
x == y = x ‘integerEq‘ y
data Tree a = EmptyTree | Node a (Tree a) (Tree a)
deriving (Show, Read)
instance (Eq a) => Eq (Tree a) where
EmptyTree == EmptyTree = True
(Node a l1 r1) == (Node b l2 r2) =
(a==b) && (l1 == l2) && (r1 == r2)
_ == _ = False
class Eq a where
(==), (/=) :: a -> a -> Bool
x /= y = not (x == y)
class (Eq a) => Ord a where
(<), (<=), (>=), (>) :: a -> a -> Bool
max, min :: a -> a -> a
#==# - списки равны или являются идентичными по перевороту:
[1,2,3] #==# [1,2,3] -- True
[1,1,1] #==# [1,1,2] -- False
[1,2,3] #==# [3,2,1] -- True
class Itch a where
(#==#) :: a -> a -> Bool
instance (Eq a) => Itch [a] where
[] #==# [] = True
x #==# y = (x == reverse y) || (x == y)
lol a b = a #==# b
> :t lol
lol :: Itch a => a -> a -> Bool
#==# - списки являются одинаковыми множествами (Set):
[1,2,3] #==# [1,2,3] -- True
[1,1,1] #==# [1,1,2] -- False
[1,2,3] #==# [3,2,1] -- True
[1,2,2] #==# [2,1,2] -- True
[1,2,2] #==# [1,2] -- True
[1,2,15] #==# [13] -- False